package com.gupao.prototype;

/**
 * @Description: //TODO:
 * @ClassName: LoggerTest
 * @Author: msx
 * @CreateDate: 2018/3/23 15:27
 * 原型模式中的拷贝分为"浅拷贝"和"深拷贝":
    浅拷贝: 对值类型的成员变量进行值的复制,对引用类型的成员变量只复制引用,不复制引用的对象.
    深拷贝: 对值类型的成员变量进行值的复制,对引用类型的成员变量也进行引用对象的复制.
-------------------------------------------------------------------------------------------------------------------------
    原型模式多用于创建复杂的或者耗时的实例, 因为这种情况下,
    复制一个已经存在的实例可以使程序运行更高效,或者创建值相等,只是命名不一样的同类数据.
 */
public class LoggerTest {

    public static void main(String[] args) {

        //浅拷贝
        Logger logger = new Logger();
        logger.setLoggerName("登录日志");
        logger.setLoggerTime(12345l);
        LoginLogger login = new LoginLogger();
        login.setExecuteMethod("login");
        login.setParam("userId:1");
        logger.setObject(login);

        Logger cpLogger = null;
        try {
            cpLogger = (Logger)logger.clone();
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
        //结果为：浅复制前和浅复制后是否对象是否一样：685325104---------460141958，，不一样的对象 了
        System.out.println("浅复制前和浅复制后是否对象是否一样："+logger.hashCode()+"---------"+cpLogger.hashCode());
        //浅复制前和浅复制后是否值引用是否一样：登录日志---------登录日志
        System.out.println("浅复制前和浅复制后是否值类型是否一样："+logger.getLoggerName()+"---------"+cpLogger.getLoggerName());
        //浅复制前和浅复制后是否引用类型（比如对象）是否一样：1163157884---------1163157884
        System.out.println("浅复制前和浅复制后是否引用类型（比如对象）是否一样："+logger.getObject().hashCode()+"---------"+cpLogger.getObject().hashCode());
        //浅复制前和浅复制后是否引用类型的值（比如对象）是否一样：login---------login
        System.out.println("浅复制前和浅复制后是否引用类型的值（比如对象）是否一样："+((LoginLogger)logger.getObject()).getExecuteMethod()+"---------"+((LoginLogger)cpLogger.getObject()).getExecuteMethod());

        System.out.println("对复制的对象cplogger做修改..................................................................");
        cpLogger.setLoggerName("登录日志-cp");
        cpLogger.setLoggerTime(456789l);
        LoginLogger login1 = (LoginLogger)cpLogger.getObject();
        login1.setExecuteMethod("login--cp");
        login1.setParam("userId:1--cp");
        cpLogger.setObject(login1);
        //结果为：浅复制前和浅复制后是否对象是否一样：685325104---------460141958，，不一样的对象 了
        System.out.println("浅复制前和浅复制后是否对象是否一样："+logger.hashCode()+"---------"+cpLogger.hashCode());
        //浅复制前和浅复制后是否值引用是否一样：登录日志---------登录日志-cp
        System.out.println("浅复制前和浅复制后是否值类型是否一样："+logger.getLoggerName()+"---------"+cpLogger.getLoggerName());
        //浅复制前和浅复制后是否值类型是否一样：12345---------456789
        System.out.println("浅复制前和浅复制后是否值类型是否一样："+logger.getLoggerTime()+"---------"+cpLogger.getLoggerTime());
        //浅复制前和浅复制后是否引用类型（比如对象）是否一样：1163157884---------1163157884
        System.out.println("浅复制前和浅复制后是否引用类型（比如对象）是否一样："+logger.getObject().hashCode()+"---------"+cpLogger.getObject().hashCode());
        //浅复制前和浅复制后是否引用类型的值（比如对象）是否一样：login--cp---------login--cp
        System.out.println("浅复制前和浅复制后是否引用类型的值（比如对象）是否一样："+((LoginLogger)logger.getObject()).getExecuteMethod()+"---------"+((LoginLogger)cpLogger.getObject()).getExecuteMethod());

        /**
         *1.复制的对象，修改值类型的，是直接复制的，不会修改原来的数据
         * 2.复制的对象，修改值是引用型的，修改了原来的引用，他们是共同引用了一个地址，clone修改了原来的数据
         * 然而我们想要的是，对象也是互不干扰的才符合业务的逻辑，解决办法：深复制
         */


        /**
         * 深复制解决对象为新的，而不是原来的地址引用的问题
         * 实现方式：
         *  1。对深层次下面的对象，LoginLogger也做clone的方式
         *  2.对深层次下面的对象，加入新的方法，采用序列化的方式，新建对象，outPutStream和inputStream
         */
        System.out.println("对复制的对象cplogger做修改..................................................................");
        cpLogger.setLoggerName("登录日志-cp--2");
        cpLogger.setLoggerTime(852369741l);
        LoginLogger login2 =null;
        try {
            login2 =(LoginLogger)((LoginLogger) cpLogger.getObject()).clone();
        } catch (Exception e) {
        	// TODO: handle exception
        	e.printStackTrace();
        }
        login2.setExecuteMethod("login--cp--2");
        login2.setParam("userId:1--cp--2");
        cpLogger.setObject(login2);
        //结果为：浅复制前和浅复制后是否对象是否一样：685325104---------460141958，，不一样的对象 了
        System.out.println("浅复制前和浅复制后是否对象是否一样："+logger.hashCode()+"---------"+cpLogger.hashCode());
        //浅复制前和浅复制后是否值引用是否一样：登录日志---------登录日志-cp--2
        System.out.println("浅复制前和浅复制后是否值类型是否一样："+logger.getLoggerName()+"---------"+cpLogger.getLoggerName());
        //浅复制前和浅复制后是否值类型是否一样：112345---------852369741
        System.out.println("浅复制前和浅复制后是否值类型是否一样："+logger.getLoggerTime()+"---------"+cpLogger.getLoggerTime());
        //浅复制前和浅复制后是否引用类型（比如对象）是否一样：1163157884---------1956725890,,不一样了
        System.out.println("浅复制前和浅复制后是否引用类型（比如对象）是否一样："+logger.getObject().hashCode()+"---------"+cpLogger.getObject().hashCode());
        //浅复制前和浅复制后是否引用类型的值（比如对象）是否一样：login--cp---------login--cp--2，，不一样了
        System.out.println("浅复制前和浅复制后是否引用类型的值（比如对象）是否一样："+((LoginLogger)logger.getObject()).getExecuteMethod()+"---------"+((LoginLogger)cpLogger.getObject()).getExecuteMethod());

        /**
         *
         */
    }
}
